package com.remedios.MqConfig;

import com.alibaba.fastjson2.JSON;
import com.remedios.service.MailSendLogService;
import com.ruoyi.common.core.constant.RabbitMqConstants;
import com.ruoyi.system.api.domain.MailSendLog;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.retry.MessageRecoverer;
import org.springframework.amqp.rabbit.retry.RepublishMessageRecoverer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @
 */
@Configuration
@Slf4j
public class RabbitMqConfig {

    @Autowired
    private CachingConnectionFactory cachingConnectionFactory;
    @Autowired
    private MailSendLogService mailSendLogService;


    @Bean
    public TopicExchange emailExchange() {
        return new TopicExchange(RabbitMqConstants.EMAIL_EXCHANGE, true, false);
    }

    @Bean
    public TopicExchange retryExchange() {
        return new TopicExchange(RabbitMqConstants.RETRY_EXCHANGE, true, false);

    }

    @Bean
    public TopicExchange dlExchange() {
        return new TopicExchange(RabbitMqConstants.FAILED_EXCHANGE, true, false);
    }

    @Bean
    public Queue emailQueue() {
        return QueueBuilder.durable(RabbitMqConstants.EMAIL_QUEUE) // 指定队列名称，并持久化
                .deadLetterExchange(RabbitMqConstants.FAILED_EXCHANGE) // 指定死信交换机
                .build();
    }





    @Bean
    public MessageRecoverer republishMessageRecoverer(RabbitTemplate rabbitTemplate) {
        return new RepublishMessageRecoverer(rabbitTemplate, RabbitMqConstants.FAILED_EXCHANGE, RabbitMqConstants.FAILED_DELIVER_ROUTING_KEY);
    }


    @Bean
    public Queue retryQueue() {

        Map<String, Object> args = new ConcurrentHashMap<>(3);
        // 将消息重新投递到exchange中
        args.put(RabbitMqConstants.X_DEL_EXCHANGE, RabbitMqConstants.EMAIL_EXCHANGE);
        args.put(RabbitMqConstants.X_DEL_ROUTING_KEY, RabbitMqConstants.EMAIL_RETRY_ROUTING_KEY);
        args.put(RabbitMqConstants.X_DEL_TTL, 30 * 1000);
        return QueueBuilder.durable(RabbitMqConstants.RETRY_QUEUE).withArguments(args).build();
    }


    /**
     * 失败队列
     *
     * @return
     */
    @Bean
    public Queue failedQueue() {
        return QueueBuilder.durable(RabbitMqConstants.FAILED_QUEUE).build();
    }


    @Bean
    public Binding topicQueueBinding() {

        return new Binding(
                RabbitMqConstants.EMAIL_QUEUE,
                Binding.DestinationType.QUEUE,
                RabbitMqConstants.EMAIL_EXCHANGE,
                "email.email.*",
                null
        );

    }

    @Bean
    public Binding retryDirectBinding() {
        return new Binding(
                RabbitMqConstants.RETRY_QUEUE,
                Binding.DestinationType.QUEUE,
                RabbitMqConstants.RETRY_EXCHANGE,
                "email.retry.*",
                null
        );

    }

    @Bean
    public Binding failDirectBinding() {
        return new Binding(
                RabbitMqConstants.FAILED_QUEUE,
                Binding.DestinationType.QUEUE,
                RabbitMqConstants.FAILED_EXCHANGE,
                "email.failed.*",
                null
        );
    }

    @Bean
    RabbitTemplate rabbitTemplate() {
        RabbitTemplate rabbitTemplate = new RabbitTemplate(cachingConnectionFactory);
        rabbitTemplate.setConfirmCallback((data, ack, cause) -> {
            MailSendLog mailSendLog = new MailSendLog();
            String msgId = data.getId();
            mailSendLog.setMsgId(msgId);
            if (ack) {
                mailSendLog.setStatus(1);
                mailSendLogService.updateMailSendLog(mailSendLog);
            } else {
                mailSendLog.setStatus(0);
                mailSendLogService.updateMailSendLog(mailSendLog);
            }
        });
        rabbitTemplate.setReturnCallback((msg, repCode, repText, exchange, routingkey) -> {

        });
        return rabbitTemplate;
    }
}
